#include "gtkbinlayout.h"
#include "gtkcssnodeprivate.h"
+#include "gtkgestureclick.h"
#include "gtkintl.h"
+#include "gtkmain.h"
#include "gtkwidget.h"
#include "gtkwidgetprivate.h"
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
+static void
+gtk_list_item_click_gesture_pressed (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ GtkListItem *self)
+{
+ GtkWidget *widget = GTK_WIDGET (self);
+ GdkModifierType state;
+ GdkEvent *event;
+ gboolean extend, modify;
+
+ if (!self->selectable)
+ {
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ event = gtk_gesture_get_last_event (GTK_GESTURE (gesture),
+ gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture)));
+ state = gdk_event_get_modifier_state (event);
+ extend = (state & GDK_SHIFT_MASK) != 0;
+ modify = (state & GDK_CONTROL_MASK) != 0;
+
+ gtk_widget_activate_action (GTK_WIDGET (self),
+ "list.select-item",
+ "(ubb)",
+ self->position, modify, extend);
+
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_ACTIVE, FALSE);
+
+ if (gtk_widget_get_focus_on_click (widget))
+ gtk_widget_grab_focus (widget);
+}
+
+static void
+gtk_list_item_click_gesture_released (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ GtkListItem *self)
+{
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE);
+}
+
+static void
+gtk_list_item_click_gesture_canceled (GtkGestureClick *gesture,
+ GdkEventSequence *sequence,
+ GtkListItem *self)
+{
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE);
+}
+
static void
gtk_list_item_init (GtkListItem *self)
{
+ GtkGesture *gesture;
+
self->selectable = TRUE;
+ gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
+
+ gesture = gtk_gesture_click_new ();
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
+ GTK_PHASE_BUBBLE);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
+ FALSE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture),
+ GDK_BUTTON_PRIMARY);
+ g_signal_connect (gesture, "pressed",
+ G_CALLBACK (gtk_list_item_click_gesture_pressed), self);
+ g_signal_connect (gesture, "released",
+ G_CALLBACK (gtk_list_item_click_gesture_released), self);
+ g_signal_connect (gesture, "cancel",
+ G_CALLBACK (gtk_list_item_click_gesture_canceled), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
}
-GtkWidget *
+GtkListItem *
gtk_list_item_new (const char *css_name)
{
+ GtkListItem *result;
+
g_return_val_if_fail (css_name != NULL, NULL);
- return g_object_new (GTK_TYPE_LIST_ITEM,
- "css-name", css_name,
- NULL);
+ result = g_object_new (GTK_TYPE_LIST_ITEM,
+ "css-name", css_name,
+ NULL);
+
+ return result;
}
/**
self->selectable = selectable;
+ gtk_widget_set_can_focus (GTK_WIDGET (self), self->selectable);
+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTABLE]);
}
return self;
}
-GtkListItem *
-gtk_list_item_factory_create (GtkListItemFactory *self)
+void
+gtk_list_item_factory_setup (GtkListItemFactory *self,
+ GtkListItem *list_item)
{
- GtkWidget *result;
-
- g_return_val_if_fail (GTK_IS_LIST_ITEM_FACTORY (self), NULL);
-
- result = gtk_list_item_new ("row");
+ g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
if (self->setup_func)
- self->setup_func (GTK_LIST_ITEM (result), self->user_data);
-
- return GTK_LIST_ITEM (result);
+ self->setup_func (list_item, self->user_data);
}
void
gpointer user_data,
GDestroyNotify user_destroy);
-GtkListItem * gtk_list_item_factory_create (GtkListItemFactory *self);
+void gtk_list_item_factory_setup (GtkListItemFactory *self,
+ GtkListItem *list_item);
void gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
#include "gtklistitemmanagerprivate.h"
+#include "gtklistitemprivate.h"
#include "gtkwidgetprivate.h"
struct _GtkListItemManager
g_return_val_if_fail (GTK_IS_LIST_ITEM_MANAGER (self), NULL);
g_return_val_if_fail (prev_sibling == NULL || GTK_IS_WIDGET (prev_sibling), NULL);
- result = gtk_list_item_factory_create (self->factory);
+ result = gtk_list_item_new ("row");
+ gtk_list_item_factory_setup (self->factory, result);
item = g_list_model_get_item (G_LIST_MODEL (self->model), position);
selected = gtk_selection_model_is_selected (self->model, position);
#include "gtklistitem.h"
+#include "gtklistitemmanagerprivate.h"
+
G_BEGIN_DECLS
-GtkWidget * gtk_list_item_new (const char *css_name);
+GtkListItem * gtk_list_item_new (const char *css_name);
void gtk_list_item_set_item (GtkListItem *self,
gpointer item);
}
}
+static void
+gtk_list_view_select_item (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ GtkListView *self = GTK_LIST_VIEW (widget);
+ GtkSelectionModel *selection_model;
+ guint pos;
+ gboolean modify, extend;
+
+ selection_model = gtk_list_item_manager_get_model (self->item_manager);
+ g_variant_get (parameter, "(ubb)", &pos, &modify, &extend);
+
+ /* XXX: handle extend by tracking the item to extend from */
+
+ if (modify)
+ {
+ if (gtk_selection_model_is_selected (selection_model, pos))
+ gtk_selection_model_unselect_item (selection_model, pos);
+ else
+ gtk_selection_model_select_item (selection_model, pos, FALSE);
+ }
+ else
+ {
+ gtk_selection_model_select_item (selection_model, pos, TRUE);
+ }
+}
+
static void
gtk_list_view_class_init (GtkListViewClass *klass)
{
g_object_class_install_properties (gobject_class, N_PROPS, properties);
+ /**
+ * GtkListView|list.select-item:
+ * @position: position of item to select
+ * @modify: %TRUE to toggle the existing selection, %FALSE to select
+ * @extend: %TRUE to extend the selection
+ *
+ * Changes selection.
+ *
+ * If @extend is %TRUE and the model supports selecting ranges, the
+ * affected items are all items from the last selected item to the item
+ * in @position.
+ * If @extend is %FALSE or selecting ranges is not supported, only the
+ * item in @position is affected.
+ *
+ * If @modify is %TRUE, the affected items will be set to the same state.
+ * If @modify is %FALSE, the affected items will be selected and
+ * all other items will be deselected.
+ */
+ gtk_widget_class_install_action (widget_class,
+ "list.select-item",
+ "(ubb)",
+ gtk_list_view_select_item);
+
gtk_widget_class_set_css_name (widget_class, I_("list"));
}